package com.pactera.madp.cp.common.util;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.hutool.json.XML;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.pactera.madp.common.core.exception.CheckedException;
import com.pactera.madp.cp.api.entity.BehaviorTrackTextMsg;
import com.pactera.madp.cp.api.entity.CorpEntity;
import com.pactera.madp.cp.api.entity.WorkAgentEntity;
import com.pactera.madp.cp.common.constant.Constant;
import com.pactera.madp.cp.common.constant.CouponApiConst;
import com.pactera.madp.cp.common.constant.WxApiConst;
import com.pactera.madp.cp.config.CouponConfig;
import com.pactera.madp.cp.mapper.WorkAgentMapper;
import com.pactera.madp.cp.mapper.corp.CorpMapper;
import com.pactera.madp.cp.service.ICorpService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.File;
import java.util.*;

import static com.pactera.madp.cp.common.constant.WxApiConst.*;

/**
 * @author: yangpengwei
 * @time: 2020/12/11 4:29 下午
 * @description 微信 api 调用工具类
 */
@Slf4j
@Component
public class WxApiUtils {

    private static final String CONST_ACCESS_TOKEN_INVALID = "-1";

    private static final Integer TOKEN_TICKET_TIMEOUT = 7000;

    //private static Map<String, String> map = new HashMap<>(0);

    private static CorpMapper corpMapper;

    private static WorkAgentMapper workAgentMapper;

    /**
     * 企业
     */
//    @Autowired
    private static ICorpService corpService;

    @Autowired
    public void setCorpService(ICorpService corpService) {
        WxApiUtils.corpService = corpService;
    }

    @Autowired
    public void setCorpMapper(CorpMapper corpMapper) {
        WxApiUtils.corpMapper = corpMapper;
    }

    @Autowired
    public void setWorkAgentMapper(WorkAgentMapper workAgentMapper) {
        WxApiUtils.workAgentMapper = workAgentMapper;
    }

    /**
     * 获取企业信息
     *
     * @param corpId 企业 Id
     * @return 企业实体
     */
    private static CorpEntity getCorpEntity(int corpId) {
        return corpMapper.selectById(corpId);
    }

    /**
     * 获取应用信息
     *
     * @param agentId 应用 Id
     * @return 企业实体
     */
    private static WorkAgentEntity getAgentEntity(int agentId) {
        //return workAgentMapper.selectById(agentId);
        QueryWrapper<WorkAgentEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("wx_agent_id", agentId);
        return workAgentMapper.selectOne(queryWrapper);
    }

    /**
     * 获取 accessToken
     *
     * @param wxCorpId 企业微信 id
     * @param secret   业务相关 secret
     * @return accessToken
     */
    public static String getAccessToken(String wxCorpId, String secret) {
        String accessTokenUrl = API_ACCESS_TOKEN + "?corpid=" + wxCorpId + "&corpsecret=" + secret;
        String respJson = HttpClientUtil.doGet(accessTokenUrl);

        log.error("getAccessToken: " + respJson);

        JSONObject jsonObject = JSON.parseObject(respJson);
        int errCode = jsonObject.getIntValue("errcode");
        if (errCode == 0) {
            String accessToken = jsonObject.getString("access_token");
            return accessToken;
        }
        return null;
    }

    /**
     * 获取通讯录相关 accessToken, 优先从缓存中获取
     *
     * @param corpId 企业 id
     * @return accessToken
     */
    public static String getAccessTokenEmployee(int corpId) {
        String keyAccess = "cp:token:emp" + corpId;
        String accessToken = (String) RedisUtil.get(keyAccess);
        if (StrUtil.isEmpty(accessToken)) {
            synchronized (WxApiUtils.class) {
                if (StrUtil.isEmpty(accessToken)) {
                    accessToken = getNewAccessTokenEmployee(corpId);
                }
            }
        }
        return accessToken;
    }

    /**
     * 获取通讯录相关 accessToken, 直接获取新的
     *
     * @param corpId 企业 id
     * @return accessToken
     */
    public static String getNewAccessTokenEmployee(int corpId) {
        CorpEntity corpEntity = getCorpEntity(corpId);
        String wxCorpId = corpEntity.getWxCorpId();
        String employSecret = corpEntity.getEmployeeSecret();
        String accessToken = getAccessToken(wxCorpId, employSecret);
        String keyAccess = "cp:token:emp" + corpId;
        if (StrUtil.isEmpty(accessToken)) {
            log.error(keyAccess + "获取失败");
            throw new CheckedException("Employee-Token获取失败");
        }
        //存入缓存
        RedisUtil.set(keyAccess, accessToken, TOKEN_TICKET_TIMEOUT);
        return accessToken;
    }

    /**
     * 获取企业微信自建应用相关 accessToken, 优先从缓存中获取
     *
     * @param agentId 应用 id
     * @return accessToken
     */
    public static String getAccessTokenAgent(int corpId, int agentId) {
        String keyAccess = "cp:token:" + corpId + "agent" + agentId;
        String accessToken = (String) RedisUtil.get(keyAccess);
        if (StrUtil.isEmpty(accessToken)) {
            synchronized (WxApiUtils.class) {
                if (StrUtil.isEmpty(accessToken)) {
                    accessToken = getNewAccessTokenAgent(corpId, agentId);
                }
            }
        }
        return accessToken;
    }

    /**
     * 获取通讯录相关 accessToken, 直接获取新的
     *
     * @param agentId 企业 id
     * @return accessToken
     */
    public static String getNewAccessTokenAgent(int corpId, int agentId) {
        CorpEntity corpEntity = getCorpEntity(corpId);
        String wxCorpId = corpEntity.getWxCorpId();
        WorkAgentEntity entity = getAgentEntity(agentId);
        if (entity == null) {
            throw new CheckedException("corpEntity获取失败，联系后台管理员查看agent是否配置");
        }
        String wxSecret = entity.getWxSecret();
        String accessToken = getAccessToken(wxCorpId, wxSecret);
        String keyAccess = "cp:token:" + corpId + "agent" + agentId;
        if (StrUtil.isEmpty(accessToken)) {
            log.error(keyAccess + "获取失败");
            throw new CheckedException("Agent-Token获取失败");
        }
        //存入缓存
        RedisUtil.set(keyAccess, accessToken, TOKEN_TICKET_TIMEOUT);
        log.info("缓存token成功：" + keyAccess);
        return accessToken;
    }

    /**
     * 获取客户相关 accessToken, 优先从缓存中获取
     *
     * @param corpId 企业 id
     * @return accessToken
     */
    public static String getAccessTokenContact(int corpId) {
        String keyAccess = "cp:token:con" + corpId;
        String accessToken = (String) RedisUtil.get(keyAccess);
        if (StrUtil.isEmpty(accessToken)) {
            synchronized (WxApiUtils.class) {
                if (StrUtil.isEmpty(accessToken)) {
                    accessToken = getNewAccessTokenContact(corpId);
                }
            }
        }
        return accessToken;
    }

    /**
     * 获取通讯录相关 accessToken, 直接获取新的
     *
     * @param corpId 企业 id
     * @return accessToken
     */
    public static String getNewAccessTokenContact(int corpId) {
        CorpEntity corpEntity = getCorpEntity(corpId);
        String wxCorpId = corpEntity.getWxCorpId();
        String secret = corpEntity.getContactSecret();
        String accessToken = getAccessToken(wxCorpId, secret);
        String keyAccess = "cp:token:con" + corpId;
        if (StrUtil.isEmpty(accessToken)) {
            log.error(keyAccess + "获取失败");
            throw new CheckedException("Contact-Token获取失败");
        }
        //存入缓存
        RedisUtil.set(keyAccess, accessToken, TOKEN_TICKET_TIMEOUT);
        return accessToken;
    }

    /**
     * 获取部门列表
     *
     * @param corpId 企业 id
     * @return 部门列表 json
     */
    public static String requestDepartmentListApi(int corpId, Integer wxDeptId) {
        String url = API_DEPARTMENT_LIST + "?access_token=" + getAccessTokenEmployee(corpId);
        if (wxDeptId != null) {
            url += "&id=" + wxDeptId;
        }
        String key = "department";
        String respJson = doGetResult(url, key);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_DEPARTMENT_LIST + "?access_token=" + getNewAccessTokenEmployee(corpId);
            if (wxDeptId != null) {
                url += "&id=" + wxDeptId;
            }
            respJson = doGetResult(url, key);
        }
        return respJson;
    }

    /**
     * 创建企业部门
     *
     * @param corpId
     * @return
     */
    public static String requestDepartmentCreateApi(int corpId, String deptBody) {
        String url = API_DEPARTMENT_CREATE + "?access_token=" + getAccessTokenEmployee(corpId);
        String key = "id";
        String respJson = doPostResult(url, key, deptBody);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_DEPARTMENT_CREATE + "?access_token=" + getNewAccessTokenEmployee(corpId);
            respJson = doPostResult(url, key, deptBody);
        }
        return respJson;
    }

    /**
     * 更新企业部门
     *
     * @param corpId
     * @return
     */
    public static String requestDepartmentUpdateApi(int corpId, String deptBody) {
        String url = API_DEPARTMENT_UPDATE + "?access_token=" + getAccessTokenEmployee(corpId);
        String key = "errcode";
        String respJson = doPostResult(url, key, deptBody);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_DEPARTMENT_UPDATE + "?access_token=" + getNewAccessTokenEmployee(corpId);
            respJson = doPostResult(url, key, deptBody);
        }
        return respJson;
    }

    /**
     * 删除企业部门
     *
     * @param corpId
     * @return
     */
    public static String requestDepartmentDeleteApi(int corpId, int id) {
        String url = API_DEPARTMENT_DELETE + "?access_token=" + getAccessTokenEmployee(corpId) + "&id=" + id;
        String key = "errcode";
        String respJson = doGetResult(url, key);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_DEPARTMENT_DELETE + "?access_token=" + getNewAccessTokenEmployee(corpId) + "&id=" + id;
            respJson = doGetResult(url, key);
        }
        return respJson;
    }

    /**
     * 获取部门员工列表
     *
     * @param corpId         企业 id
     * @param wxDepartmentId 企业微信部门 id
     * @return 员工列表 json
     */
    public static String requestUserListApi(int corpId, int wxDepartmentId) {
        String url = API_USER_LIST
                + "?access_token=" + getAccessTokenEmployee(corpId)
                + "&department_id=" + wxDepartmentId
                + "&fetch_child=0";
        String key = "userlist";
        String respJson = doGetResult(url, key);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_USER_LIST
                    + "?access_token=" + getNewAccessTokenEmployee(corpId)
                    + "&department_id=" + wxDepartmentId
                    + "&fetch_child=0";
            respJson = doGetResult(url, key);
        }
        return respJson;
    }

    /**
     * 获取员工详情
     *
     * @param agentId 应用 id
     * @param code    通过成员授权获取到的code
     * @return 员工列表 json
     */
    public static String requestWxUserIdApi(int corpId, int agentId, String code) {
        String url = API_USER_INFO
                + "?access_token=" + getAccessTokenAgent(corpId, agentId)
                + "&code=" + code;
        String key = "UserId";
        String respJson = doGetResult(url, key);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_USER_LIST
                    + "?access_token=" + getNewAccessTokenAgent(corpId, agentId)
                    + "&code=" + code;
            respJson = doGetResult(url, key);
        }
        return respJson;
    }

    /**
     * 获取开启外部联系人权限的微信员工 id 列表
     *
     * @param corpId 企业 id
     * @return 开启外部联系人权限的微信员工 id 列表 json
     */
    public static String requestFollowUserListApi(int corpId) {
        String url = API_FOLLOW_USER_LIST + "?access_token=" + getAccessTokenContact(corpId);
        String key = "follow_user";
        String respJson = doGetResult(url, key);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_FOLLOW_USER_LIST + "?access_token=" + getNewAccessTokenContact(corpId);
            respJson = doGetResult(url, key);
        }
        return respJson;
    }


    /**
     * 获取员工客户相关统计数据
     *
     * @param corpId   企业 id
     * @param wxUserId 微信员工 id
     * @return 员工客户相关统计数据 json
     */
    public static String getUserBehaviorData(int corpId, String wxUserId) {
        String reqUrl = API_USER_BEHAVIOR_DATA + "?access_token=" + getAccessTokenContact(corpId);

        long endTime = System.currentTimeMillis();
        long startTime = endTime - DateUtils.MILLIS_DAY;

        JSONObject reqJson = new JSONObject();
        reqJson.put("userid", new String[]{wxUserId});
        reqJson.put("start_time", startTime / 1000);
        reqJson.put("end_time", endTime / 1000);

        String paramJson = reqJson.toJSONString();
        String key = "behavior_data";
        String respJson = doPostResult(reqUrl, key, paramJson);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            reqUrl = API_USER_BEHAVIOR_DATA + "?access_token=" + getNewAccessTokenContact(corpId);
            respJson = doPostResult(reqUrl, key, paramJson);
        }
        return respJson;
    }

    public static String getUserBehaviorData(int corpId, String wxUserId, long startTime, long endTime) {
        String reqUrl = API_USER_BEHAVIOR_DATA + "?access_token=" + getAccessTokenContact(corpId);
        JSONObject reqJson = new JSONObject();
        reqJson.put("userid", new String[]{wxUserId});
        reqJson.put("start_time", startTime / 1000);
        reqJson.put("end_time", endTime / 1000);

        String paramJson = reqJson.toJSONString();
        String key = "behavior_data";
        String respJson = doPostResult(reqUrl, key, paramJson);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            reqUrl = API_USER_BEHAVIOR_DATA + "?access_token=" + getNewAccessTokenContact(corpId);
            respJson = doPostResult(reqUrl, key, paramJson);
        }
        return respJson;
    }

    /**
     * 获取企业标签库
     *
     * @param corpId 企业 id
     * @return 获取企业客户所有标签详情 json
     */
    public static String requestGetAllTag(int corpId) {
        return requestGetTagDetail(corpId, null);
    }

    /**
     * 获取企业标签库里某个标签详情
     *
     * @param corpId  企业 id
     * @param wxTagId 微信 tagId
     * @return 获取企业客户标签详情 json
     */
    public static String requestGetTagDetail(int corpId, String wxTagId) {
        String reqUrl = API_GET_CORP_TAG_LIST + "?access_token=" + getAccessTokenContact(corpId);

        String paramJson = "";
        if (wxTagId != null) {
            JSONObject reqJson = new JSONObject();
            reqJson.put("tag_id", new String[]{wxTagId});
            paramJson = reqJson.toJSONString();
        }

        String key = "tag_group";
        String respJson = doPostResult(reqUrl, key, paramJson);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            reqUrl = API_GET_CORP_TAG_LIST + "?access_token=" + getNewAccessTokenContact(corpId);
            respJson = doPostResult(reqUrl, key, "");
        }
        return respJson;
    }

    /**
     * 编辑企业客户标签组
     *
     * @param corpId  企业 id
     * @param wxTagId 微信标签组 id / 微信标签 id
     * @param tagName 微信标签组名 / 微信标签名
     */
    public static void requestEditTag(int corpId, String wxTagId, String tagName) {
        String reqUrl = API_EDIT_CORP_TAG + "?access_token=" + getAccessTokenContact(corpId);

        JSONObject reqJson = new JSONObject();
        reqJson.put("id", wxTagId);
        reqJson.put("name", tagName);
        String paramJson = reqJson.toJSONString();

        String respJson = doPostResult(reqUrl, null, paramJson);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            reqUrl = API_EDIT_CORP_TAG + "?access_token=" + getNewAccessTokenContact(corpId);
            doPostResult(reqUrl, null, paramJson);
        }
    }

    /**
     * 删除微信标签组
     *
     * @param corpId       企业 id
     * @param wxTagGroupId 微信标签组 id
     */
    public static void requestDelGroupTag(int corpId, String wxTagGroupId) {
        requestDelTag(corpId, wxTagGroupId, true);
    }

    /**
     * 删除微信标签
     *
     * @param corpId       企业 id
     * @param wxTagGroupId 微信标签 id
     */
    public static void requestDelTag(int corpId, String wxTagGroupId) {
        requestDelTag(corpId, wxTagGroupId, false);
    }

    public static void requestDelTag(int corpId, String wxTagId, boolean isGroup) {
        String reqUrl = API_DEL_CORP_TAG + "?access_token=" + getAccessTokenContact(corpId);

        String key = isGroup ? "group_id" : "tag_id";
        JSONObject reqJson = new JSONObject();
        reqJson.put(key, new String[]{wxTagId});
        String paramJson = reqJson.toJSONString();

        String respJson = doPostResult(reqUrl, null, paramJson);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            reqUrl = API_DEL_CORP_TAG + "?access_token=" + getNewAccessTokenContact(corpId);
            doPostResult(reqUrl, null, paramJson);
        }
    }

    public static void requestDelTags(int corpId, List<String> tagIds) {
        String reqUrl = API_DEL_CORP_TAG + "?access_token=" + getAccessTokenContact(corpId);

        JSONObject reqJson = new JSONObject();
        reqJson.put("tag_id", tagIds);
        String paramJson = reqJson.toJSONString();

        String respJson = doPostResult(reqUrl, null, paramJson);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            reqUrl = API_DEL_CORP_TAG + "?access_token=" + getNewAccessTokenContact(corpId);
            doPostResult(reqUrl, null, paramJson);
        }
    }

    public static String requestCreateGroupAndTag(int corpId, String tagGroupName, String tagName) {
        List<String> tagList = new ArrayList<>(1);
        tagList.add(tagName);
        return requestCreateGroupAndTags(corpId, tagGroupName, tagList);
    }

    public static String requestCreateTag(int corpId, String wxTagGroupId, String tagName) {
        List<String> tagList = new ArrayList<>(1);
        tagList.add(tagName);
        return requestCreateTags(corpId, wxTagGroupId, tagList);
    }

    public static String requestCreateGroupAndTags(int corpId, String tagGroupName, List<String> tagNameList) {
        String groupKey = "group_name";
        return requestCreateTags(corpId, groupKey, tagGroupName, tagNameList);
    }

    public static String requestCreateTags(int corpId, String wxGroupId, List<String> tagNameList) {
        String groupKey = "group_id";
        return requestCreateTags(corpId, groupKey, wxGroupId, tagNameList);
    }

    public static String requestCreateTags(int corpId, String groupKey, String groupValue, List<String> tagNameList) {
        String reqUrl = API_ADD_CORP_TAG + "?access_token=" + getAccessTokenContact(corpId);

        List<JSONObject> tagList = new ArrayList<>();
        for (String tagName : tagNameList) {
            JSONObject tagJson = new JSONObject();
            tagJson.put("name", tagName);
            tagList.add(tagJson);
        }

        JSONObject reqJson = new JSONObject();
        reqJson.put(groupKey, groupValue);
        reqJson.put("tag", tagList);
        String paramJson = reqJson.toJSONString();

        String key = "tag_group";
        String respJson = doPostResult(reqUrl, key, paramJson);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            reqUrl = API_ADD_CORP_TAG + "?access_token=" + getNewAccessTokenContact(corpId);
            respJson = doPostResult(reqUrl, key, paramJson);
        }
        return respJson;
    }

    public static String requestCreateContactWay(int corpId, boolean skipVerify, String state, List<String> wxUserIdList) {
        String reqUrl = API_ADD_CONTACT_WAY + "?access_token=" + getAccessTokenContact(corpId);

        JSONObject reqJson = new JSONObject();
        reqJson.put("type", "2");
        reqJson.put("scene", "2");
        reqJson.put("skip_verify", skipVerify);
        reqJson.put("state", state);
        reqJson.put("user", wxUserIdList);
        String paramJson = reqJson.toJSONString();

        log.debug("requestCreateContactWay: " + paramJson);

        String key = "";
        String respJson = doPostResult(reqUrl, key, paramJson);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            reqUrl = API_ADD_CONTACT_WAY + "?access_token=" + getNewAccessTokenContact(corpId);
            respJson = doPostResult(reqUrl, key, paramJson);
        }
        return respJson;
    }

    public static String requestCreateContactWay(int corpId, boolean skipVerify, List<String> wxUserIdList) {
        String reqUrl = API_ADD_CONTACT_WAY + "?access_token=" + getAccessTokenContact(corpId);

        JSONObject reqJson = new JSONObject();
        reqJson.put("type", "1");
        reqJson.put("scene", "2");
        reqJson.put("skip_verify", skipVerify);
        reqJson.put("user", wxUserIdList);
        String paramJson = reqJson.toJSONString();

        log.debug("requestCreateContactWay: " + paramJson);

        String key = "";
        String respJson = doPostResult(reqUrl, key, paramJson);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            reqUrl = API_ADD_CONTACT_WAY + "?access_token=" + getNewAccessTokenContact(corpId);
            respJson = doPostResult(reqUrl, key, paramJson);
        }
        return respJson;
    }

    public static String requestCreateContactWay(
            int corpId,
            int type,
            boolean skipVerify,
            String state,
            List<?> wxUserIdList,
            List<?> wxDepartmentIdList
    ) {
        String reqUrl = API_ADD_CONTACT_WAY + "?access_token=" + getAccessTokenContact(corpId);

        JSONObject reqJson = new JSONObject();
        reqJson.put("type", type);
        reqJson.put("scene", "2");
        reqJson.put("skip_verify", skipVerify);
        reqJson.put("state", state);
        reqJson.put("user", wxUserIdList);
        reqJson.put("party", wxDepartmentIdList);
        String paramJson = reqJson.toJSONString();

        log.debug("requestCreateContactWay: " + paramJson);

        String key = "";
        String respJson = doPostResult(reqUrl, key, paramJson);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            reqUrl = API_ADD_CONTACT_WAY + "?access_token=" + getNewAccessTokenContact(corpId);
            respJson = doPostResult(reqUrl, key, paramJson);
        }
        return respJson;
    }

    public static String requestCreateContactWayAndRemark(int corpId, int type, boolean skipVerify, String state, List<?> wxUserIdList, List<?> wxDepartmentIdList, String remark) {
        String reqUrl = API_ADD_CONTACT_WAY + "?access_token=" + getAccessTokenContact(corpId);
        JSONObject reqJson = new JSONObject();
        reqJson.put("type", type);
        reqJson.put("scene", "2");
        reqJson.put("skip_verify", skipVerify);
        reqJson.put("state", state);
        reqJson.put("user", wxUserIdList);
        reqJson.put("party", wxDepartmentIdList);
        reqJson.put("remark", remark);
        String paramJson = reqJson.toJSONString();

        log.debug("requestCreateContactWay: " + paramJson);

        String key = "";
        String respJson = doPostResult(reqUrl, key, paramJson);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            reqUrl = API_ADD_CONTACT_WAY + "?access_token=" + getNewAccessTokenContact(corpId);
            respJson = doPostResult(reqUrl, key, paramJson);
        }
        return respJson;
    }

    public static String requestGetContactWay(int corpId, String configId) {
        String reqUrl = API_GET_CONTACT_WAY + "?access_token=" + getAccessTokenContact(corpId);

        JSONObject reqJson = new JSONObject();
        reqJson.put("config_id", configId);
        String paramJson = reqJson.toJSONString();

        String key = "";
        String respJson = doPostResult(reqUrl, key, paramJson);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            reqUrl = API_UPDATE_CONTACT_WAY + "?access_token=" + getNewAccessTokenContact(corpId);
            respJson = doPostResult(reqUrl, key, paramJson);
        }
        return respJson;
    }

    public static void updateContactWay(int corpId, String wxConfigId, List<?> wxUserIdList, boolean skipVerify) {
        updateContactWay(corpId, wxConfigId, wxUserIdList, Collections.emptyList(), skipVerify);
    }

    public static void updateContactWay(int corpId, String wxConfigId, List<?> wxUserIdList, List<?> wxDepartmentIdList, boolean skipVerify) {
        String reqUrl = API_UPDATE_CONTACT_WAY + "?access_token=" + getAccessTokenContact(corpId);

        JSONObject reqJson = new JSONObject();
        reqJson.put("config_id", wxConfigId);
        reqJson.put("user", wxUserIdList);
        reqJson.put("party", wxDepartmentIdList);
        reqJson.put("skip_verify", skipVerify);
        String paramJson = reqJson.toJSONString();

        log.debug("requestUpdateContactWay: " + paramJson);

        String key = null;
        String respJson = doPostResult(reqUrl, key, paramJson);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            reqUrl = API_UPDATE_CONTACT_WAY + "?access_token=" + getNewAccessTokenContact(corpId);
            doPostResult(reqUrl, key, paramJson);
        }
    }

    public static void requestUpdateContactWay(int corpId, String wxConfigId, List<?> wxUserIdList, List<?> wxDepartmentIdList, boolean skipVerify) {
        String reqUrl = API_UPDATE_CONTACT_WAY + "?access_token=" + getAccessTokenContact(corpId);

        JSONObject reqJson = new JSONObject();
        reqJson.put("config_id", wxConfigId);
        reqJson.put("user", wxUserIdList);
        reqJson.put("party", wxDepartmentIdList);
        reqJson.put("skip_verify", skipVerify);
        String paramJson = reqJson.toJSONString();

        log.debug("requestUpdateContactWay: " + paramJson);

        String key = null;
        String respJson = doPostResult(reqUrl, key, paramJson);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            reqUrl = API_UPDATE_CONTACT_WAY + "?access_token=" + getNewAccessTokenContact(corpId);
            doPostResult(reqUrl, key, paramJson);
        }
    }

    /**
     * @description:同步客户群列表
     * @return:
     * @author: Huayu
     * @time: 2020/12/17 17:53
     */
    public static String getWorkRoomIndexData(CorpEntity corpEntity, String ownerId) {
        String reqUrl = API_GET_WORKROOM_LIST + "?access_token=" + getAccessTokenContact(corpEntity.getCorpId());
        List<JSONObject> workRoomList = new ArrayList<>();
        JSONObject workRoomJson = new JSONObject();
        workRoomJson.put("userid_list", ownerId);
        workRoomJson.put("partyid_list", null);
        workRoomList.add(workRoomJson);
        JSONObject reqJson = new JSONObject();
        reqJson.put("status_filter", 0);
        //reqJson.put("owner_filter", workRoomList);
        //reqJson.put("offset", 0);
        reqJson.put("limit", 10);
        String key = "group_chat_list";
        String paramJson = reqJson.toJSONString();
        String respJson = doPostResult(reqUrl, key, paramJson);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            reqUrl = API_GET_WORKROOM_LIST + "?access_token=" + getNewAccessTokenContact(corpEntity.getCorpId());
            respJson = doPostResult(reqUrl, key, paramJson);
        }
        return respJson;
    }

    /**
     * @description:同步客户群详情
     * @return:
     * @author: Huayu
     * @time: 2020/12/17 17:53
     */
    public static String getWorkRoomInfoData(CorpEntity corpEntity, String chatId) {
        String reqUrl = API_GET_WORKROOM_INFO + "?access_token=" + getAccessTokenContact(corpEntity.getCorpId());
        List<JSONObject> workRoomList = new ArrayList<>();
        JSONObject reqJson = new JSONObject();
        reqJson.put("chat_id", chatId);
        String key = "group_chat";
        String paramJson = reqJson.toJSONString();
        String respJson = doPostResult(reqUrl, key, paramJson);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            reqUrl = API_GET_WORKROOM_INFO + "?access_token=" + getNewAccessTokenContact(corpEntity.getCorpId());
            respJson = doPostResult(reqUrl, key, paramJson);
        }
        return respJson;

    }

    /**
     * 修改客户备注信息
     *
     * @param corpId
     * @param map
     * @return
     */
    public static String updateExternalContact(Integer corpId, Map<String, Object> map) {
        String reqUrl = API_EDIT_EXTERNAL_REMARK + "?access_token=" + getAccessTokenContact(corpId);
        JSONObject reqJson = new JSONObject();
        reqJson.put("userid", map.get("userid"));
        reqJson.put("external_userid", map.get("external_userid"));
        reqJson.put("remark", map.get("remark"));
        reqJson.put("description", map.get("description"));
        String key = null;
        String paramJson = reqJson.toJSONString();
        String respJson = doPostResult(reqUrl, key, paramJson);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            reqUrl = API_GET_WORKROOM_INFO + "?access_token=" + getNewAccessTokenContact(corpId);
            respJson = doPostResult(reqUrl, key, paramJson);
        }
        return respJson;

    }

    /**
     * 获取客户列表
     *
     * @param corpId
     * @return
     */
    public static String getExternalContactList(Integer corpId, String userId) {
        String reqUrl = API_GET_EXTERNAL_LIST + "?access_token=" + getAccessTokenContact(corpId) + "&userid=" + userId;
        String key = "";
        String respJson = doGetResult(reqUrl, key);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            reqUrl = API_GET_WORKROOM_INFO + "?access_token=" + getNewAccessTokenContact(corpId);
            respJson = doGetResult(reqUrl, key);
        }
        return respJson;

    }

    /**
     * 获取客户详情
     *
     * @param corpId
     * @return
     */
    public static String getExternalContactInfo(Integer corpId, String externalUserid) {
        String reqUrl = API_GET_EXTERNAL_INFO + "?access_token=" + getAccessTokenContact(corpId) + "&external_userid=" + externalUserid;
        String key = "";
        String respJson = doGetResult(reqUrl, key);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            reqUrl = API_GET_WORKROOM_INFO + "?access_token=" + getNewAccessTokenContact(corpId);
            respJson = doGetResult(reqUrl, key);
        }
        return respJson;

    }

    /**
     * @description: 发送欢迎语
     * @author: Huayu
     * @time: 2021/3/29 17:23
     */
    public static String sendWelcomeCode(Integer corpId, Map<String, Object> sendWelcomeDataMap, Map<String, Object> sendWelcomeTextDataMap, String welcomeCode) {
        String reqUrl = API_ADD_WELCOME_MSG + "?access_token=" + getAccessTokenContact(corpId);
        HashMap<String, Object> map = new HashMap<>();
        List list = new LinkedList<>();
        map.put("welcome_code", welcomeCode);
        if (!sendWelcomeDataMap.isEmpty()) {
            list.add(sendWelcomeDataMap);
            map.put("attachments", list);
        }
        if (!sendWelcomeTextDataMap.isEmpty()) {
            map.put("text", sendWelcomeTextDataMap.get("text"));
        }
        JSONObject jsonObject = new JSONObject(map);
        String s = jsonObject.toJSONString();
        String respJson = doPostResult(reqUrl, "", s);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            reqUrl = API_GET_WORKROOM_INFO + "?access_token=" + getNewAccessTokenContact(corpId);
            respJson = doPostResult(reqUrl, "", s);
        }
        return respJson;

    }

    /**
     * @author: yangpengwei
     * @time: 2021/3/23 4:44 下午
     * @description 获取指定的应用详情
     */
    public static String getAgentInfo(String wxCorpId, String wxAgentId, String wxAgentSecret) {
        String accessToken = getAccessToken(wxCorpId, wxAgentSecret);
        String paramUrl = "?access_token=" + accessToken + "&agentid=" + wxAgentId;
        String url = API_GET_AGENT_INFO + paramUrl;
        String key = "";
        String respJson = doGetResult(url, key);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            accessToken = getAccessToken(wxCorpId, wxAgentSecret);
            paramUrl = "?access_token=" + accessToken + "&agentid=" + wxAgentId;
            url = API_GET_AGENT_INFO + paramUrl;
            respJson = doGetResult(url, key);
        }
        return respJson;
    }

    /**
     * 上传临时素材
     *
     * @param corpId 企业 id
     * @param file   素材文件
     * @return 素材文件 id
     */
    public static String uploadImageToTemp(Integer corpId, File file) {
        String url = API_UPLOAD_FILE_TO_TEMP + "?type=image&access_token=" + getAccessTokenEmployee(corpId);
        String key = "media_id";
        String respJson = doPostResult(url, key, file);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_UPLOAD_FILE_TO_TEMP + "?type=image&access_token=" + getNewAccessTokenEmployee(corpId);
            respJson = doPostResult(url, key, file);
        }
        return respJson;
    }

    /**
     * 获取临时素材
     *
     * @param corpId  企业 id
     * @param mediaId 素材id
     * @return 素材文件
     */
    public static String getFromTemp(Integer corpId, String mediaId) {
        String url = API_GET_FILE_TO_TEMP + "?access_token=" + getAccessTokenEmployee(corpId) + "&media_id=" + mediaId;
        String key = "";
        String respJson = doGetResult(url, key);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_GET_FILE_TO_TEMP + "?type=image&access_token=" + getNewAccessTokenEmployee(corpId) + "&media_id=" + mediaId;
            respJson = doGetResult(url, key);
        }
        return respJson;
    }

    /**
     * 获取企业的全部群发记录
     *
     * @param corpId
     * @param requestBody
     * @return
     */
    public static String getGroupmsgList(Integer corpId, String requestBody) {
        String url = API_GET_GROUPMSG_LIST + "?access_token=" + getAccessTokenContact(corpId);
        String respJson = doPostResult(url, "", requestBody);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_GET_GROUPMSG_LIST + "?access_token=" + getNewAccessTokenContact(corpId);
            respJson = doPostResult(url, "", requestBody);
        }
        return respJson;
    }


    /**
     * 获取群发成员发送任务列表
     *
     * @param corpId
     * @param requestBody
     * @return
     */
    public static String getGroupmsgTask(Integer corpId, String requestBody) {
        String url = API_GET_GROUPMSG_TASK + "?access_token=" + getAccessTokenContact(corpId);
        String key = "";
        String respJson = doPostResult(url, key, requestBody);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_GET_GROUPMSG_TASK + "?access_token=" + getNewAccessTokenContact(corpId);
            respJson = doPostResult(url, key, requestBody);
        }
        return respJson;
    }


    /**
     * 获取企业群发成员执行结果
     *
     * @param corpId
     * @param requestBody
     * @return
     */
    public static String getGroupmsgSendResult(Integer corpId, String requestBody) {
        String url = API_GET_GROUPMSG_SEND_RESULT + "?access_token=" + getAccessTokenContact(corpId);
        String key = "";
        String respJson = doPostResult(url, key, requestBody);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_GET_GROUPMSG_SEND_RESULT + "?access_token=" + getNewAccessTokenContact(corpId);
            respJson = doPostResult(url, key, requestBody);
        }
        return respJson;
    }

    /**
     * 上传临时文件 按type
     *
     * @param corpId
     * @param file
     * @param type
     * @return
     */
    public static String uploadImageToTemps(Integer corpId, File file, String type) {
        String url = API_UPLOAD_FILE_TO_TEMP + "?type=" + type + "&access_token=" + getAccessTokenEmployee(corpId);
        String key = "media_id";
        String respJson = doPostResult(url, key, file);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_UPLOAD_FILE_TO_TEMP + "?type=" + type + "&access_token=" + getNewAccessTokenEmployee(corpId);
            respJson = doPostResult(url, key, file);
        }
        return respJson;
    }

    /**
     * 员工在职继承
     *
     * @param corpId
     * @param oldWxUserId
     * @param newWxUserId
     * @param wxExternalUserid
     * @return
     */
    public static String contactInherit(Integer corpId, String oldWxUserId, String newWxUserId, String[] wxExternalUserid) {
        JSONObject reqJson = new JSONObject();
        reqJson.put("handover_userid", oldWxUserId);
        reqJson.put("takeover_userid", newWxUserId);
        reqJson.put("external_userid", wxExternalUserid);
        String requestBody = reqJson.toString();
        String url = API_POST_ON_INHERIT + "?access_token=" + getAccessTokenContact(corpId);
        String key = "customer";
        String respJson = doPostResult(url, key, requestBody);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_POST_ON_INHERIT + "?access_token=" + getAccessTokenContact(corpId);
            respJson = doPostResult(url, key, requestBody);
        }
        return respJson;
    }

    /**
     * 客户继承状态查询
     *
     * @param corpId
     * @param oldWxUserId
     * @param newWxUserId
     * @return
     */
    public static String contactInheritStatus(Integer corpId, String oldWxUserId, String newWxUserId) {
        JSONObject reqJson = new JSONObject();
        reqJson.put("handover_userid", oldWxUserId);
        reqJson.put("takeover_userid", newWxUserId);
        String requestBody = reqJson.toString();
        String url = API_POST_ON_USER_INHERIT + "?access_token=" + getAccessTokenContact(corpId);
        String key = "customer";
        String respJson = doPostResult(url, key, requestBody);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_POST_ON_USER_INHERIT + "?access_token=" + getAccessTokenContact(corpId);
            respJson = doPostResult(url, key, requestBody);
        }
        return respJson;
    }

    /**
     * 创建企业内部群
     *
     * @param corpId
     * @param name
     * @param owner
     * @param userlist
     * @param agentId
     * @return
     */
    public static String saveAppChatCreate(Integer corpId, String name, String owner, List<String> userlist, int agentId) {
        JSONObject object = new JSONObject();
        object.put("name", name);
        object.put("owner", owner);
        object.put("userlist", userlist);
        String requestBody = object.toString();
        String url = API_POST_APPCHAT_CREATE + "?access_token=" + getAccessTokenAgent(corpId, agentId);
        String key = "chatid";
        String respJson = doPostResult(url, key, requestBody);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_POST_APPCHAT_CREATE + "?access_token=" + getNewAccessTokenAgent(corpId, agentId);
            respJson = doPostResult(url, key, requestBody);
        }
        return respJson;
    }

    /**
     * 获取内部群信息
     *
     * @param corpId
     * @param chatId
     * @param agentId
     * @return
     */
    public static String appChatGet(Integer corpId, String chatId, Integer agentId) {
        String url = API_GET_APPCHAT_GET + "?access_token=" + getAccessTokenAgent(corpId, agentId) + "&chatid=" + chatId;
        String key = "chat_info";
        String respJson = doGetResult(url, key);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_GET_APPCHAT_GET + "?access_token=" + getNewAccessTokenAgent(corpId, agentId) + "&chatid=" + chatId;
            respJson = doGetResult(url, key);
        }
        return respJson;
    }

    public static String appChatUpdate(Integer agentId, String chatId, String name, String owner, List<String> addUserList, List<String> delUserList, Integer corpId) {
        String url = API_POST_APPCHAT_UPDATE + "?access_token=" + getAccessTokenAgent(corpId, agentId);
        JSONObject object = new JSONObject();
        object.put("chatid", chatId);
        if (!StrUtil.isBlank(name)) {
            object.put("name", name);
        }
        if (!StrUtil.isBlank(owner)) {
            object.put("owner", owner);
        }
        if (!addUserList.isEmpty()) {
            object.put("add_user_list", addUserList);
        }
        if (!delUserList.isEmpty()) {
            object.put("del_user_list", delUserList);
        }
        String key = "errcode";
        String requestBody = object.toString();
        String respJson = doPostResult(url, key, requestBody);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_POST_APPCHAT_UPDATE + "?access_token=" + getNewAccessTokenAgent(corpId, agentId);
            respJson = doPostResult(url, key, requestBody);
        }
        return respJson;
    }


    /**
     * 获取待分配的离职成员对应的客户列表
     *
     * @param corpId   企业微信id
     * @param cursor   分页游标
     * @param pageId   当前页
     * @param pageSize 分页大小
     * @return
     */
    public static String contactByResignedList(Integer corpId, String pageId, String pageSize, String cursor) {
        String url = API_POST_RESIGNED_CONTACT_INHERIT + "?access_token=" + getAccessTokenContact(corpId);
        JSONObject reqJson = new JSONObject();
        reqJson.put("cursor", cursor);
        reqJson.put("page_id", pageId);
        reqJson.put("page_size", pageSize);
        String requestBody = reqJson.toString();
        String key = "info";
        String respJson = doPostResult(url, key, requestBody);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_POST_RESIGNED_CONTACT_INHERIT + "?access_token=" + getAccessTokenContact(corpId);
            respJson = doPostResult(url, key, requestBody);
        }
        return respJson;
    }

    /**
     * 分配离职成员的客户
     *
     * @param corpId
     * @param oldWxUserId
     * @param newWxUserId
     * @param wxExternalUserid
     * @return
     */
    public static String contactByResigned(Integer corpId, String oldWxUserId, String newWxUserId, String[] wxExternalUserid) {
        JSONObject reqJson = new JSONObject();
        reqJson.put("handover_userid", oldWxUserId);
        reqJson.put("takeover_userid", newWxUserId);
        reqJson.put("external_userid", wxExternalUserid);
        String requestBody = reqJson.toString();
        String url = API_POST_RESIGNED_INHERIT + "?access_token=" + getAccessTokenContact(corpId);
        String key = "customer";
        String respJson = doPostResult(url, key, requestBody);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_POST_RESIGNED_INHERIT + "?access_token=" + getAccessTokenContact(corpId);
            respJson = doPostResult(url, key, requestBody);
        }
        return respJson;
    }

    /**
     * 读取成员
     *
     * @param userid
     * @param corpId
     * @return
     */
    public static String getUser(String userid, Integer corpId) {
        String url = API_POST_USER_GET + "?access_token=" + getAccessTokenEmployee(corpId) + "&userid=" + userid;
        String key = "";
        String respJson = doGetResult(url, key);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_POST_USER_GET + "?access_token=" + getAccessTokenEmployee(corpId) + "&userid=" + userid;
            respJson = doGetResult(url, key);
        }
        return respJson;
    }

    /**
     * 创建成员
     *
     * @param map
     * @param corpId
     * @return
     */
    public static String createUser(Map<String, Object> map, Integer corpId) {
        String url = API_POST_USER_CREATE + "?access_token=" + getAccessTokenEmployee(corpId);
//        String key = null;
        String respJson = doPostResults(url, "", JSONObject.toJSONString(map));
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_POST_USER_CREATE + "?access_token=" + getNewAccessTokenEmployee(corpId);
            respJson = doPostResults(url, "", map.toString());
        }
        return respJson;
    }

    /**
     * 更新成员
     *
     * @param map
     * @param corpId
     * @return
     */
    public static String updateUser(Map<String, Object> map, Integer corpId) {
        String url = API_POST_USER_UPDATE + "?access_token=" + getAccessTokenEmployee(corpId);
//        String key = null;
        String respJson = doPostResult(url, "", JSONObject.toJSONString(map));
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_POST_USER_UPDATE + "?access_token=" + getAccessTokenEmployee(corpId);
            respJson = doPostResult(url, "", map.toString());
        }
        return respJson;
    }

    /**
     * 删除成员
     *
     * @param userid
     * @param corpId
     * @return
     */
    public static String deleteUser(String userid, Integer corpId) {
        String url = API_POST_USER_DELETE + "?access_token=" + getAccessTokenEmployee(corpId) + "&userid=" + userid;
        String key = "";
        String respJson = doGetResults(url, key);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_POST_USER_DELETE + "?access_token=" + getAccessTokenEmployee(corpId) + "&userid=" + userid;
            respJson = doGetResults(url, key);
        }
        return respJson;
    }

    /**
     * 分配离职成员的客户群
     *
     * @param corpId
     * @param groupId
     * @param newWxUserId
     * @return
     */
    public static String contactByResignedGroup(Integer corpId, String[] groupId, String newWxUserId) {
        JSONObject reqJson = new JSONObject();
        reqJson.put("chat_id_list", groupId);
        reqJson.put("takeover_userid", newWxUserId);
        String requestBody = reqJson.toString();
        String url = API_POST_GROUP_RESIGNED_INHERIT + "?access_token=" + getAccessTokenContact(corpId);
        String key = "failed_chat_list";
        String respJson = doPostResult(url, key, requestBody);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_POST_GROUP_RESIGNED_INHERIT + "?access_token=" + getAccessTokenContact(corpId);
            respJson = doPostResult(url, key, requestBody);
        }
        return respJson;
    }


    public static String getJsapiTicketOfCorp(int corpId) {
        String ticketKey = "cp:ticket:corp" + corpId;
        String ticket = (String) RedisUtil.get(ticketKey);
        if (ticket == null) {
            return getNewJsapiTicketOfCorp(corpId);
        }
        return ticket;
    }

    public static String getNewJsapiTicketOfCorp(int corpId) {
        String url = API_GET_JSAPI_TICKET_CORP + "?access_token=" + getAccessTokenContact(corpId);
        String key = "ticket";
        String respJson = doGetResult(url, key);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_GET_JSAPI_TICKET_CORP + "?access_token=" + getNewAccessTokenContact(corpId);
            respJson = doGetResult(url, key);
        }
        if (!StrUtil.isEmpty(respJson)) {
            String ticketKey = "cp:ticket:corp" + corpId;
            RedisUtil.set(ticketKey, respJson, TOKEN_TICKET_TIMEOUT);
            log.info("企业" + corpId + "-ticket获取成功");
        }
        return respJson;
    }

    public static String getJsapiTicketOfApp(int corpId, int agentId) {
        String ticketKey = "cp:ticket:corp" + corpId + ":app" + agentId;
        String ticket = (String) RedisUtil.get(ticketKey);
        if (ticket == null) {
            return getNewJsapiTicketOfApp(corpId, agentId);
        }
        return ticket;
    }

    public static String getNewJsapiTicketOfApp(int corpId, int agentId) {
        String url = API_GET_JSAPI_TICKET_APP + "?access_token=" + getAccessTokenAgent(corpId, agentId) + "&type=agent_config";
        String key = "ticket";
        String respJson = doGetResult(url, key);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_GET_JSAPI_TICKET_APP + "?access_token=" + getNewAccessTokenAgent(corpId, agentId) + "&type=agent_config";
            respJson = doGetResult(url, key);
        }
        if (!StrUtil.isEmpty(respJson)) {
            String ticketKey = "cp:ticket:corp" + corpId + ":app" + agentId;
            RedisUtil.set(ticketKey, respJson, TOKEN_TICKET_TIMEOUT);
            log.info("应用" + agentId + "-ticket获取成功");
        }
        return respJson;
    }

    private static String doGetResult(String url, String key) {
        log.debug(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ");
        log.debug("url: " + url);
        String respJson = HttpClientUtil.doGet(url);
        respJson = doGetResultAndCheck(url, respJson, 1);
        log.debug("respJson: " + respJson);
        log.debug("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ");
        return getResultData(respJson, key);
    }

    private static String doGetResults(String url, String key) {
        log.debug(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ");
        log.debug("url: " + url);
        String respJson = HttpClientUtil.doGet(url);
        respJson = doGetResultAndCheck(url, respJson, 1);
        log.debug("respJson: " + respJson);
        log.debug("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ");
        return getResultDatas(respJson, key);
    }

    private static String doPostResult(String url, String key, String requestBody) {
        log.debug(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ");
        log.debug("url: " + url);
        log.debug("requestBody: " + requestBody);
        String respJson = HttpClientUtil.doPost(url, requestBody);
        log.debug("respJson: " + respJson);
        log.debug("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ");
        return getResultData(respJson, key);
    }

    private static String doPostResults(String url, String key, String requestBody) {
        log.debug(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ");
        log.debug("url: " + url);
        log.debug("requestBody: " + requestBody);
        String respJson = HttpClientUtil.doPost(url, requestBody);
        log.debug("respJson: " + respJson);
        log.debug("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ");
        return getResultDatas(respJson, key);
    }

    private static String doPostResult(String url, String key, File requestBody) {
        String respJson = HttpClientUtil.doPost(url, requestBody);
        return getResultData(respJson, key);
    }

    private static String doPostResultOfXml(String url, String xmlBody) {
        log.debug(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ");
        log.debug("url: " + url);
        log.debug("xmlBody: " + xmlBody);
        String respXml = HttpClientUtil.doPost(url, xmlBody);
        log.debug("respXml: " + respXml);
        log.debug("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ");
        return respXml;
    }

    private static String doPostCoupon(String url, String requestBody) {
        log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ");
        log.info("url: " + url);
        log.info("xmlBody: " + requestBody);
        String respJson =  HttpClientUtil.doPost(url, requestBody);
        log.info("respJson: " + respJson);
        log.info("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ");
        return respJson;
    }

    private static String getResultData(String result, String key) {
        log.debug(key + " : " + result);

        JSONObject jsonObject = JSON.parseObject(result);
        int errCode = jsonObject.getIntValue("errcode");
        if (errCode == 42001) {
            return CONST_ACCESS_TOKEN_INVALID;
        }
        if (errCode == 0) {
            if (key == null) {
                return "";
            } else if (key.isEmpty()) {
                return result;
            } else {
                return jsonObject.getString(key);
            }
        }
        String err = errCode + "：" + jsonObject.get("errmsg");
        log.error(err);
        return null;
    }

    private static String getResultDatas(String result, String key) {
        log.debug(key + " : " + result);

        JSONObject jsonObject = JSON.parseObject(result);
        int errCode = jsonObject.getIntValue("errcode");
        if (errCode == 42001) {
            return CONST_ACCESS_TOKEN_INVALID;
        }
        if (key == null) {
            return "";
        } else if (key.isEmpty()) {
            return result;
        } else {
            return jsonObject.getString(key);
        }
    }

    /**
     * 清空所有缓存的 accessToken
     */
    public static void clear() {
        //map.clear();
    }

    @SneakyThrows
    private static String doGetResultAndCheck(String url, String result, int repeatNum) {
        JSONObject jsonObject = JSON.parseObject(result);
        int errCode = jsonObject.getIntValue("errcode");
        if (errCode == 45033) {
            Thread.sleep(RandomUtil.randomLong(200, 500));
            result = HttpClientUtil.doGet(url);
            log.warn(url + " : " + repeatNum++);
            result = doGetResultAndCheck(url, result, repeatNum);
        }
        return result;
    }

    private static boolean isJSON(String json) {
        if ("{}".equals(json) || (json.length() > 2 && json.charAt(0) == '{' && json.charAt(json.length() - 1) == '}')) {
            try {
                JSONObject obj = JSON.parseObject(json);
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
            return true;
        }
        return false;
    }

    /**
     * @param corpId
     * @return 获取企业微信所有朋友圈列表
     */
    public static String getMoment(int corpId) {
        String url = API_POST_MOMENT_LIST + "?access_token=" + getAccessTokenContact(corpId);
        String key = "moment_list";
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.DATE, -30);
        long startTime = instance.getTimeInMillis() / 1000;

        long endTime = DateUtil.date().getTime() / 1000;
        HashMap<String, Long> map = new HashMap<>();
        map.put("start_time", startTime);
        map.put("end_time", endTime);
        String reqBody = JSONObject.toJSONString(map);
        String respJson = doPostResult(url, key, reqBody);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_FOLLOW_USER_LIST + "?access_token=" + getNewAccessTokenContact(corpId);
            respJson = doPostResult(url, key, reqBody);
        }
        return respJson;
    }

    /**
     * @param corpId
     * @param startDate
     * @param endDate
     * @return 获取起止日期内的企业微信朋友圈列表
     */
    public static String getMomentByDate(int corpId, String startDate, String endDate) {
        String url = API_POST_MOMENT_LIST + "?access_token=" + getAccessTokenContact(corpId);
        String key = "moment_list";
        DateTime beginOfDay = DateUtil.beginOfDay(DateUtil.parseDate(startDate));
        DateTime endOfDay = DateUtil.endOfDay(DateUtil.parseDate(endDate));
        long startTime = beginOfDay.getTime() / 1000;

        long endTime = endOfDay.getTime() / 1000;
        HashMap<String, Long> map = new HashMap<>();
        map.put("start_time", startTime);
        map.put("end_time", endTime);
        String reqBody = JSONObject.toJSONString(map);
        String respJson = doPostResult(url, key, reqBody);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_FOLLOW_USER_LIST + "?access_token=" + getNewAccessTokenContact(corpId);
            respJson = doPostResult(url, key, reqBody);
        }
        return respJson;
    }

    public static String getMomentTask(int corpId, String moment_id) {
        String url = API_POST_MOMENT_TASK + "?access_token=" + getAccessTokenContact(corpId);
        String key = "task_list";
        HashMap<String, String> map = new HashMap<>();
        map.put("moment_id", moment_id);
        String reqBody = JSONUtil.toJsonStr(map);
        String respJson = doPostResult(url, key, reqBody);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_FOLLOW_USER_LIST + "?access_token=" + getNewAccessTokenContact(corpId);
            respJson = doPostResult(url, key, reqBody);
        }
        return respJson;
    }

    public static String getMomentComments(int corpId, String moment_id, String userId) {
        String url = API_POST_MOMENT_COMMENT + "?access_token=" + getAccessTokenContact(corpId);
        String key = "";
        HashMap<String, String> map = new HashMap<>();
        map.put("moment_id", moment_id);
        map.put("userid", userId);
        String reqBody = JSONObject.toJSONString(map);
        String respJson = doPostResult(url, key, reqBody);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_FOLLOW_USER_LIST + "?access_token=" + getNewAccessTokenContact(corpId);
            respJson = doPostResult(url, key, reqBody);
        }
        return respJson;
    }

    /**
     * 给成员发消息
     *
     * @param textMsg
     * @param corpId
     */
    public static void sendMsgToEmployee(BehaviorTrackTextMsg textMsg, Integer corpId) {
        //获取token
        String accessToken = WxApiUtils.getAccessTokenAgent(corpId, textMsg.getAgentid());
        String msgUrl = WxApiConst.API_ADD_MESSAGE.replace("ACCESS_TOKEN", accessToken);
        log.info("msgUrl:{}", msgUrl);
        log.info("msg:{}", textMsg);
//        HttpUtil.post(msgUrl, JSONUtil.toJsonStr(textMsg));
        String respJson = HttpClientUtil.doPost(msgUrl, JSONUtil.toJsonStr(textMsg));

    }

    /**
     * 给成员发消息
     *
     * @param textMsg
     * @param corpId
     */
    public static void sendMsgToEmployeeByString(String textMsg, Integer corpId, String wxCorpId) {
        //获取token
        //获取发送应用id
//        String accessToken = WxApiUtils.getAccessTokenAgent(corpId,SendMsgAgentEnum.findByType(wxCorpId).getAgentId());
        String accessToken = WxApiUtils.getAccessTokenAgent(corpId, corpService.getWxSendMsgAgentIdByWxCorpId(wxCorpId));
        String msgUrl = WxApiConst.API_ADD_MESSAGE.replace("ACCESS_TOKEN", accessToken);
        log.info("msgUrl:{}", msgUrl);
        log.info("msg:{}", textMsg);
//        String post = HttpUtil.post(msgUrl, textMsg);
        String respJson = HttpClientUtil.doPost(msgUrl, JSONUtil.toJsonStr(textMsg));
        log.info("<<<<<<<<<<<<<<<<<<resp>>>>>>>>>>>>>>>>>>>>>>>:{}", respJson);
    }

    /**
     * 给成员发图文消息
     *
     * @param textMsg
     * @param corpId
     */
    public static void sendMsgToEmployeeByLink(String textMsg, Integer corpId, String wxCorpId) {
        //获取token
//        Integer agentId = SendMsgAgentEnum.findByType(wxCorpId).getAgentId();
        Integer agentId = corpService.getWxSendMsgAgentIdByWxCorpId(wxCorpId);
        String accessToken = WxApiUtils.getAccessTokenAgent(corpId, agentId);

        String msgUrl = WxApiConst.API_ADD_MESSAGE.replace("ACCESS_TOKEN", accessToken);
        log.info("msgUrl:{}", msgUrl);
        log.info("msg:{}", textMsg);
//        String str = HttpUtil.post(msgUrl,textMsg);
        String respJson = HttpClientUtil.doPost(msgUrl, JSONUtil.toJsonStr(textMsg));
        System.out.println(respJson);
    }

    /**
     * 给成员群发消息
     *
     * @param obj
     * @param corpId
     * @return
     */
    public static String sendMsgToGroup(Object obj, Integer corpId) {
        String accessToken = WxApiUtils.getAccessTokenAgent(corpId, Constant.SEND_MSG_AGENT_ID);
        String msgUrl = WxApiConst.API_POST_GROUP_SEND.replace("ACCESS_TOKEN", accessToken);
//        String respJson = HttpUtil.post(msgUrl, JSONUtil.toJsonStr(obj));
        String respJson = HttpClientUtil.doPost(msgUrl, JSONUtil.toJsonStr(obj));
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            msgUrl = API_POST_GROUP_SEND + "?access_token=" + getNewAccessTokenContact(corpId);
//            respJson = HttpUtil.post(msgUrl, JSONUtil.toJsonStr(obj));
            respJson = HttpClientUtil.doPost(msgUrl, JSONUtil.toJsonStr(obj));
        }
        cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(respJson);
        Integer errcode = jsonObject.get("errcode", Integer.class);
        if (!errcode.equals(0)) throw new CheckedException("api返回失败");
        return respJson;
    }

    /**
     * 获得朋友圈的可见范围
     *
     * @param corpId
     * @param momentId
     * @param userId
     * @return
     */
    public static String getMomentRange(Integer corpId, String momentId, String userId) {
        String accessToken = WxApiUtils.getAccessTokenAgent(corpId, Constant.SEND_MSG_AGENT_ID);
        HashMap<String, String> map = new HashMap<>();
        map.put("moment_id", momentId);
        map.put("userid", userId);
        String msgUrl = WxApiConst.API_POST_MOMENT_RANGE.replace("ACCESS_TOKEN", accessToken);
//        String respJson = HttpUtil.post(msgUrl, JSONUtil.toJsonStr(map));
        String respJson = HttpClientUtil.doPost(msgUrl, JSONUtil.toJsonStr(map));
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            msgUrl = API_POST_MOMENT_RANGE + "?access_token=" + getNewAccessTokenContact(corpId);
//            respJson = HttpUtil.post(msgUrl, JSONUtil.toJsonStr(map));
            respJson = HttpClientUtil.doPost(msgUrl, JSONUtil.toJsonStr(map));
        }
        return respJson;
    }

    /**
     * 推送消息到内部群
     *
     * @param corpId
     * @return
     */
    public static String sendMsgToGroupChat(Object obj, Integer corpId, String wxCorpId) {
        String url = API_SEND_MSG + "?access_token=" + getAccessTokenAgent(corpId, corpService.getWxSendMsgAgentIdByWxCorpId(wxCorpId));
        String key = "errcode";
        String respJson = doPostResult(url, key, JSONUtil.toJsonStr(obj));
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_SEND_MSG + "?access_token=" + getNewAccessTokenAgent(corpId, corpService.getWxSendMsgAgentIdByWxCorpId(wxCorpId));
            respJson = doPostResult(url, key, JSONUtil.toJsonStr(obj));
        }
        return respJson;
    }

    /**
     * 批量异步全量覆盖部门
     *
     * @return
     */
    public static String asyncBatchParty(Integer corpId, String requestBody) {
        String url = API_POST_BATCH_PARTY + "?access_token=" + getAccessTokenEmployee(corpId);
        String respJson = doPostResult(url, "jobid", requestBody);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_POST_BATCH_PARTY + "?access_token=" + getAccessTokenEmployee(corpId);
            respJson = doPostResult(url, "jobid", requestBody);
        }
        return respJson;
    }

    /**
     * 批量异步全量覆盖成员
     *
     * @param corpId
     * @param requestBody
     * @return
     */
    public static String asyncBatchUser(Integer corpId, String requestBody) {
        String url = API_POST_BATCH_USER + "?access_token=" + getAccessTokenEmployee(corpId);
        String respJson = doPostResult(url, "jobid", requestBody);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_POST_BATCH_USER + "?access_token=" + getAccessTokenEmployee(corpId);
            respJson = doPostResult(url, "jobid", requestBody);
        }
        return respJson;
    }

    /**
     * 获取异步任务结果
     *
     * @param corpId
     * @param jobId
     * @return
     */
    public static String getAsyncBatchResult(Integer corpId, String jobId) {
        String url = API_GET_BATCH_GETRESULT + "?access_token=" + getAccessTokenEmployee(corpId) + "&jobid=" + jobId;
        String respJson = doGetResult(url, "");
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = API_GET_BATCH_GETRESULT + "?access_token=" + getAccessTokenEmployee(corpId) + "&jobid=" + jobId;
            respJson = doGetResult(url, "");
        }
        return respJson;
    }

    /**
     * 发布朋友圈任务
     *
     * @param corpId
     * @param requestBody
     * @return
     */
    public static String addMomentTask(Integer corpId, String requestBody) {
        String url = ADD_MOMENT_TASK + "?access_token=" + getAccessTokenContact(corpId);

        String respJson = doPostResult(url, "jobid", requestBody);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = ADD_MOMENT_TASK + "?access_token=" + getAccessTokenContact(corpId);
            respJson = doPostResult(url, "jobid", requestBody);
        }
        return respJson;
    }

    /**
     * 上传附件（朋友圈或者商品图册）
     *
     * @param corpId
     * @param file
     * @param type
     * @param attachmentType
     * @return
     */
    public static String uploadAttachment(Integer corpId, File file, String type, Integer attachmentType) {
        String url = UPLOAD_ATTACHMENT + "?access_token=" + getAccessTokenContact(corpId) + "&media_type=" + type + "&attachment_type=" + attachmentType;
        String key = "media_id";
        String respJson = doPostResult(url, key, file);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = UPLOAD_ATTACHMENT + "?access_token=" + getNewAccessTokenContact(corpId) + "&media_type=" + type + "&attachment_type=" + attachmentType;
            respJson = doPostResult(url, key, file);
        }
        return respJson;
    }


    /**
     * 获取企业全部的发表列表
     *
     * @param corpId
     * @param requestBody
     * @return
     */
    public static String getMomentList(Integer corpId, String requestBody) {
        String url = GET_MOMENT_LIST + "?access_token=" + getAccessTokenContact(corpId);

        String respJson = doPostResult(url,"", requestBody);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = GET_MOMENT_LIST + "?access_token=" + getAccessTokenContact(corpId);
            respJson = doPostResult(url,"", requestBody);
        }
        return respJson;
    }

    /**
     * 获取客户朋友圈企业发表的列表
     *
     * @param corpId
     * @param requestBody
     * @return
     */
    public static String getMomentTask(Integer corpId, String requestBody) {
        String url = GET_MOMENT_TASK + "?access_token=" + getAccessTokenContact(corpId);

        String respJson = doPostResult(url, "task_list", requestBody);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = GET_MOMENT_TASK + "?access_token=" + getAccessTokenContact(corpId);
            respJson = doPostResult(url, "task_list", requestBody);
        }
        return respJson;
    }


    /**
     * 获取任务创建结果
     *
     * @param corpId
     * @param jobId
     * @return
     */
    public static String getMomentTaskResult(Integer corpId, String jobId) {
        String url = GET_MOMENT_TASK_RESULT + "?access_token=" + getAccessTokenContact(corpId) + "&jobid=" + jobId;

        String respJson = doGetResult(url,"result");
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = GET_MOMENT_TASK_RESULT + "?access_token=" + getNewAccessTokenContact(corpId) + "&jobid=" + jobId;
            respJson = doGetResult(url,"result");
        }
        return respJson;
    }

    /**
     * 获取客户朋友圈的互动数据
     * @param corpId
     * @param requestBody
     * @return
     */
    public static  String getMomentComments(Integer corpId, String requestBody){
        String url = GET_MOMENT_COMMENTS + "?access_token=" + getAccessTokenContact(corpId);

        String respJson = doPostResult(url, "", requestBody);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = GET_MOMENT_COMMENTS + "?access_token=" + getAccessTokenContact(corpId);
            respJson = doPostResult(url, "", requestBody);
        }
        return respJson;
    }

    /**
     * userid转openid
     * @param corpId 企业ID
     * @param userid 员工userid
     * @return 转换后的openid
     */
    public static String convertToOpenid(Integer corpId, String userid) {
        String url = POST_CONVERT_TO_OPENID + "?access_token=" + getAccessTokenEmployee(corpId);

        Map body = new HashMap();
        body.put("userid", userid);
        String requestBody = JSONUtil.toJsonStr(body);

        String respJson = doPostResult(url, "openid", requestBody);
        if (CONST_ACCESS_TOKEN_INVALID.equals(respJson)) {
            url = POST_CONVERT_TO_OPENID + "?access_token=" + getAccessTokenEmployee(corpId);
            respJson = doPostResult(url, "openid", requestBody);
        }
        return respJson;
    }

    /**
     * 发放企业红包
     * @param xmlBody xml格式报文
     * @return xml格式报文
     */
    public static String sendWorkWxRedpack(String xmlBody) {
        String url = POST_SEND_WORK_WX_REDPACK;
        return doPostResultOfXml(url, xmlBody);
    }

    /**
     * 查询红包记录
     * @param xmlBody
     * @return
     */
    public static String queryWorkWxRedpack(String xmlBody) {
        String url = POST_QUERY_WORK_WX_REDPACK;
        return doPostResultOfXml(url, xmlBody);
    }

    /**
     * 调用全流量下单接口(提供发红包数据源)
     * 调用全流量订单查询接口
     * 全流量商户API接口调用
     * @return
     */
    public static String openCouponApi(String body, String method, String sign, CouponConfig config) {
        String timestamp = DateUtil.format(new Date(), "yyyyMMddHHmmss");
        String url = CouponApiConst.API_BASE;
        url = StrUtil.format(url,config.getHost(), config.getBusinessId(), method,
                timestamp, config.getVersion(), sign);
        return doPostCoupon(url, body);
    }
}
